using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using System.Linq;

using Gtk;
using Gdk;

namespace kedhlow
{
	public class Util
	{
		//Style tags:
		public TextTag tagBold  = new TextTag("bold");
		public TextTag tagItalic  = new TextTag("italic");
		public TextTag tagUnderline  = new TextTag("underline");
		public TextTag tagStrikeout  = new TextTag("strikeout");

		public string m_LinkedWords = "";
		
		public string LinkedWordsListString
		{
			get
			{
				return m_LinkedWords;
			}
			set
			{
				m_LinkedWords = value;
			}
		}

		
		public TextBuffer DefineTextTags(TextBuffer buffer)
		{
			//Text styling tags
			tagBold.Weight = Pango.Weight.Bold;
			buffer.TagTable.Add(tagBold);
			
			tagItalic.Style = Pango.Style.Italic;
			buffer.TagTable.Add(tagItalic);
			
			tagUnderline.Underline = Pango.Underline.Single;
			buffer.TagTable.Add(tagUnderline);
			
			tagStrikeout.Strikethrough = true;
			buffer.TagTable.Add(tagStrikeout);
			
			return buffer; //Return modified buffer
		}
		
		//True if an item is selected in the specified treeview, false if not
		public bool TreeviewHasSelection(Gtk.TreeView tv)
		{
		 	TreeIter iter; TreeModel model;
		    if(tv.Selection.GetSelected(out model, out iter))
		    { return true; } 
			else { return false; }
		}
		
		//TextBuffer Serialisation methods
		public byte[] SerialiseTextBuffer(Gtk.TextBuffer txtBuffer)
		{
			TextIter start, end;
			txtBuffer.GetBounds(out start, out end);
			Gdk.Atom srlfmt = txtBuffer.RegisterDeserializeTagset(null);
			byte[] data = txtBuffer.Serialize(txtBuffer,srlfmt,start,end);
			return data;
		}		
		public Gtk.TextBuffer DeserialiseTextBuffer(byte[] data, TextTagTable tagTable)
		{
			Gtk.TextBuffer txtBuffer = new Gtk.TextBuffer(tagTable);
			Gdk.Atom srlfmt = txtBuffer.RegisterDeserializeTagset(null);
			TextIter start = txtBuffer.StartIter;
			ulong dataLength = (ulong) data.LongLength;
			txtBuffer.Deserialize(txtBuffer, srlfmt, ref start, data, dataLength);
			//TODO: Parse for HTTP links, and add tags as appropriate
			return txtBuffer;
		}
		public string ReplaceQuotes(string str)
		{
			str = str.Replace("\"","\"\"");
			str = str.Replace("'","''");
			//Console.WriteLine(str);
			return str;
		}
		public string StripSpaces(string str)
		{
			str = str.Replace(" ","");
			//Console.WriteLine(str);
			return str;
		}
		
		//Generate automatically linked items list
		public Gtk.ListStore GetRelatedItems(int itemid, KDB dbc)
		{
			//Clear linked list text:
			m_LinkedWords = "";
			
			//Init stopwords list:
			StreamReader stopText = new StreamReader("StopWordsList.txt");
            string allRead = stopText.ReadToEnd();
            stopText.Close();
			
			//Get item text to StreamReader
			string itemPlainText = dbc.GetItemPlainText(itemid);
			MemoryStream stream = new MemoryStream();
			StreamWriter writer = new StreamWriter( stream );
			writer.Write( itemPlainText ); writer.Flush();
			StreamReader reader = new StreamReader( stream );
			reader.BaseStream.Seek(0,SeekOrigin.Begin); reader.DiscardBufferedData();
			
			//Parse text, ignoring stop words
			StringBuilder wordBuffer = new StringBuilder();			
			Dictionary<string,int> wordList = new Dictionary<string, int>();
						
			while(reader.Peek() >= 0)
			{
				char c = (char) reader.Read();
				if(char.IsLetterOrDigit(c) || c=='\'' || c== '-')
				{
					wordBuffer.Append(char.ToLower(c));
				}
				else
				{
					if(wordBuffer.Length > 0)
					{
						if(!(Regex.IsMatch(allRead.ToUpper(),wordBuffer.ToString().ToUpper())))
						{
							int count = 0;
							string word = wordBuffer.ToString();
							wordList.TryGetValue(word, out count);
							wordList[word] = ++count;
						}
						wordBuffer = new StringBuilder();
					}
				}
			}
			
			//Null anything which has been used to try and free the memory:
			stream = null; itemPlainText=null; writer = null; reader = null; allRead = null; stopText = null;
			
			var sortedWordList = from item in wordList orderby item.Value descending select item;
			string SearchQuery = "";
			int i = 0;
			foreach(var item in sortedWordList.Take(5))
			{
				SearchQuery = SearchQuery + item.Key;
				m_LinkedWords = m_LinkedWords + item.Key;
				if((i<9)&&(item.Key != ""))
				{
					SearchQuery = SearchQuery + " "; 
					m_LinkedWords = m_LinkedWords +", ";
				}
				i++;
			}
			
			Gtk.ListStore ls = new Gtk.ListStore(typeof(int),typeof(string),typeof(string), typeof(string));
			//Searchable list of IDs already found
			System.Collections.Hashtable htR = new System.Collections.Hashtable();
			
			IDataReader dbReader = dbc.SearchAllCollections(SearchQuery);
			while(dbReader.Read())
			{
				if(!itemid.Equals(dbReader.GetInt32(0))) //If the returned ID is not the item we are looking at
				{
					ls.AppendValues(dbReader.GetInt32(0),dbc.GetCollectionNameByID(dbReader.GetInt32(1)),dbReader.GetString(2),Mono.Unix.Catalog.GetString("Standard")); //Add it
					htR.Add(dbReader.GetInt32(0),null);
				}
			}
			//Get low relevance listings
			dbReader = dbc.SearchAllCollections(SearchQuery, false);
			while(dbReader.Read())
			{
				if(!itemid.Equals(dbReader.GetInt32(0))) //If the returned ID is not the item we are looking at
				{
					if(!htR.ContainsKey(dbReader.GetInt32(0)))
					{
						ls.AppendValues(dbReader.GetInt32(0),dbc.GetCollectionNameByID(dbReader.GetInt32(1)),dbReader.GetString(2),Mono.Unix.Catalog.GetString("Low")); //Add it
					}
				}
			}
			htR = null;
			
			return ls;
		}
	
		private void ClearStatusbarTimeout(int Milliseconds, string ContextID, Gtk.Statusbar sb)
		{ 
		    GLib.Timeout.Add((uint) Milliseconds, new GLib.TimeoutHandler(
		        delegate()
		        {
		            sb.Pop(sb.GetContextId(ContextID));
		            return false;
		        }));
		}
	}
}